

#ifndef _EVENTLOOP_H_
#define _EVENTLOOP_H_

#include "CurrentThread.hpp"
#include "Timestamp.hpp"
#include "noncopyable.hpp"
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
#include <vector>

namespace zephyr {

class Channel;
class Poller;

// 事件循环 包含两大模块 Channel Poller
class EventLoop : noncopyable {
  public:
    using Functor = std::function<void()>;

    EventLoop();
    ~EventLoop();

    //开启事件循环
    void loop();
    // 退出事件循环
    void quit();

    void runInLoop(Functor callback);
    void queueInLoop(Functor callback);

    // 通过eventfd唤醒loop所在的线程 向eventfd发送8字节数据
    void wakeup();

    // Eventloop的方法 --> Poller的方法
    void updateChannel(Channel *channel);
    void removeChannel(Channel *channel);
    void hasChannel(Channel *channel);

    // 判断EventLoop对象是否在自己的线程里
    bool isInLoopThread() const {
        return m_threadId == CurrentThread::tid();    // threadId_为EventLoop创建时的线程id CurrentThread::tid()为当前线程id
    }

  private:
    // 给eventfd的channel绑定回调函数 当调用weakup时即有事件发生时调用handleRead读取wakefd的8字节同时唤醒阻塞的epollwait
    void handleRead();
    // 执行当前EventLoop所需要处理的回调操作
    void doPendingFunctors();

  private:

    using ChannelList = std::vector<Channel *>;

    std::atomic_bool m_looping;
    // 标志退出loop循环
    std::atomic_bool m_quit;

    // 当前EventLoop是由那个线程创建
    const pid_t m_threadId;

    // Poller返回发生事件的Channels的时间点
    Timestamp m_pollReturnTime;
    std::unique_ptr<Poller> m_poller;

    // 当mainLoop获取一个新用户的Channel 需通过轮询算法选择一个subLoop 通过该成员唤醒subLoop处理Channel
    int m_wakeupfd; // eventfd
    std::unique_ptr<Channel> m_wakeupChannel; // eventfd 绑定的channel

    // 返回Poller检测到当前有事件发生的所有channel列表
    ChannelList m_activeChannels;


    std::atomic_bool m_callingPendingFunctors; // 当前loop是否有需要执行的回调函数
    std::vector<Functor> m_pendingFunctors; // loop所有需要执行的回调函数
    std::mutex m_mtx; // 保护m_pendingFunctors线程安全
};

}

#endif // _EVENTLOOP_H_